#ifndef TYPESYSTEM_H
#define TYPESYSTEM_H
#include "StompedReality/Core.h"
#include "StompedReality/Core/TypeSystem/TypeSystemImpl.h"
namespace StompedReality
{
namespace type_system
{
/*!
 *
 * \author	Stefan Kazalski
 *
 * \brief	The Type System.
 *
 *    The type system manages all nessecary information to store and load types.
 */
class DLL_EXPORT TypeSystem
{
 private:

  static TypeSystemImpl* m_TypeSystemImpl;
  static TypeSystemImpl* m_getTypeSystemImpl( );
  TypeSystem( );
  virtual ~TypeSystem( );

 public:

  /*!
   * \brief		Adds a new type to the type system.
   *
   * \param		name	The name of the type.
   *
   * \return	The created type info.
   */
  template <typename TYPE>
  static TypeInfo* CreateTypeInfo ( const char* name )
  {
    return m_getTypeSystemImpl( )->CreateTypeInfo<TYPE> ( name );
  }

  /*!
   * \brief		Checks if a type exists by it the types id.
   *
   * \param		typeID	The types id.
   *
   * \return	True if exists otherwise false.
   */
  static bool HasType ( StompedReality::TYPE_ID typeID )
  {
    return m_getTypeSystemImpl( )->HasType ( typeID );
  }

  /*!
   * \brief		Checks if a type exists by it the types name.
   *
   * \param		typeName	The types name.
   *
   * \return	True if exists otherwise false.
   */
  static bool HasType ( const char* typeName )
  {
    return m_getTypeSystemImpl( )->HasType ( typeName );
  }

  /*!
   * \brief		Checks if a type exists.
   *
   * \return	True if exists otherwise false.
   */
  template <typename TYPE>
  static bool HasType( )
  {
    return m_getTypeSystemImpl( )->HasType< TYPE >( );
  }

  /*!
   * \brief		Get TypeInfo.
   *
   *    Return the types information or NULL if the type has no info.
   *
   * \param		typeID	The types id.
   *
   * \return	The types information or NULL if the type has no info.
   */
  static TypeInfo* GetTypeByID ( StompedReality::TYPE_ID typeID )
  {
    return m_getTypeSystemImpl( )->GetType ( typeID );
  }

  /*!
   * \brief		Get TypeInfo.
   *
   *    Return the types information or NULL if the type has no info.
   *
   * \param		typeName	The types name.
   *
   * \return	The types information or NULL if the type has no info.
   */
  static TypeInfo* GetTypeByName ( const char* typeName )
  {
    return m_getTypeSystemImpl( )->GetType ( typeName );
  }

  /*!
   * \brief		Get TypeInfo.
   *
   *    Return the types information or NULL if the type has no info.
   *
   * \return	The types information or NULL if the type has no info.
   */
  template <typename TYPE>
  static TypeInfo* GetType( )
  {
    return m_getTypeSystemImpl( )->GetType< TYPE > ( );
  }

  /*!
   * \brief	Type id conversion.
   */
  template <typename TYPE>
  static StompedReality::TYPE_ID GetTypeID( )
  {
    return m_getTypeSystemImpl( )->GetTypeID< TYPE >( );
  }

  /*!
   * \brief	Type id conversion.
   *
   * \param		typeName THe types name.
   *
   * \return	The types id.
   */
  static StompedReality::TYPE_ID GetTypeID ( const char* typeName )
  {
    return m_getTypeSystemImpl( )->GetTypeID ( typeName );
  }

};

template <typename TYPE>
static void createBase( TypeField& field, char* data )
{
  *( TYPE* ) ( data + field.offset ) = TYPE( );
};
template <typename TYPE>
static void jsonWriteBase(  char* data, int offset, Json::Value& root, const char* name = 0 )
{
  root[name] = *( TYPE* ) ( data + offset );
};
template <typename TYPE>
static void jsonReadNumber( char* data, int offset, Json::Value& root, const char* name = 0 )
{
  *( TYPE* ) ( data + offset ) = ( TYPE )root.get( name, 0 ).asDouble( );
};
static void jsonReadBool( char* data, int offset, Json::Value& root, const char* name = 0 )
{
  *( bool* ) ( data + offset ) = ( bool )root.get( name, 0 ).asBool( );
};
static void jsonReadTypeName( char* data, int offset, Json::Value& root, const char* name = 0 )
{
  *( StompedReality::TYPE_ID* ) ( data + offset ) = TypeSystem::GetTypeID( root.get( name, "" ).asCString( ) );
};
static void jsonReadString( char* data, int offset, Json::Value& root, const char* name = 0 )
{
  *( std::string* ) ( data + offset ) = root.get( name, "" ).asString( );
};
static void jsonWriteString( char* data, int offset, Json::Value& root, const char* name = 0 )
{
  root[name] = *( std::string* ) ( data + offset );
};

}
}
#endif // TYPESYSTEM_H
